package xin.clips.system.service.impl;

import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;
import xin.clips.common.core.domain.AjaxResult;
import xin.clips.common.enums.gy.*;
import xin.clips.common.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xin.clips.common.utils.bean.BeanUtils;
import xin.clips.system.domain.gy.*;
import xin.clips.system.dto.*;
import xin.clips.system.mapper.gy.*;
import xin.clips.system.service.ISysConfigService;
import xin.clips.system.service.gy.*;

/**
 * 设备管理Service业务层处理
 *
 * @author clips
 * @date 2023-01-12
 */
@Service
public class GyDeviceServiceImpl implements IGyDeviceService {
    @Autowired
    private GyDeviceMapper gyDeviceMapper;

    @Autowired
    private GyMachineParamMapper machineParamMapper;

    @Autowired
    private GyArmParamMapper armParamMapper;

    @Autowired
    private GyDeviceAlarmRecordMapper deviceAlarmRecordMapper;

    @Autowired
    private GyDeviceRecordMapper deviceRecordMapper;

    @Autowired
    private GyMachineParamRecordServiceImpl machineParamRecordService;

    @Autowired
    private IGyArmParamRecordService armParamRecordService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IGyWorkOrderService gyWorkOrderService;

    @Autowired
    private IGyDeviceEarlywarnRecordService earlywarnRecordService;

    /**
     * 查询设备管理
     *
     * @param deviceId 设备管理主键
     * @return 设备管理
     */
    @Override
    public GyDevice selectGyDeviceByDeviceId(Long deviceId) {
        return gyDeviceMapper.selectGyDeviceByDeviceId(deviceId);
    }

    /**
     * 查询设备管理列表
     *
     * @param gyDevice 设备管理
     * @return 设备管理
     */
    @Override
    public List<GyDevice> selectGyDeviceList(GyDevice gyDevice) {
        return gyDeviceMapper.selectGyDeviceList(gyDevice);
    }

    /**
     * 新增设备管理
     *
     * @param gyDevice 设备管理
     * @return 结果
     */
    @Override
    public int insertGyDevice(GyDevice gyDevice) {
        gyDevice.setCreateBy(ShiroUtils.getLoginName());
        gyDevice.setCreateTime(DateUtils.getNowDate());
        return gyDeviceMapper.insertGyDevice(gyDevice);
    }

    @Transactional
    public AjaxResult insert(GyDeviceDTO gyDeviceDTO) {
        GyDevice device = new GyDevice();
        device.setDeviceStatus(gyDeviceDTO.getDeviceStatus());
        device.setDeviceName(gyDeviceDTO.getDeviceName());
        device.setCreateTime(DateUtils.getNowDate());
        device.setLocationId(gyDeviceDTO.getLocationId());
        device.setDeviceType(gyDeviceDTO.getDeviceType());
        device.setFileName(gyDeviceDTO.getFileName());
        device.setLocation(gyDeviceDTO.getLocation());
        device.setFilePath(gyDeviceDTO.getFilePath());
        String prefix = PinyUtils.getPinyin(device.getDeviceName()).substring(0, 1);
        Integer maxId = gyDeviceMapper.selectMaxId();
        if (maxId == null) {
            maxId = 0;
        }
        device.setDeviceno(ProducerNumUtil.getId(prefix, (maxId + 1)));
        gyDeviceMapper.insertGyDevice(device);
        if (gyDeviceDTO.getDeviceType().equals(DeviceTypeEnum.MACHINE.getCode())) { //机床
            GyMachineParam machineParam = new GyMachineParam();
            BeanUtils.copyBeanProp(machineParam, gyDeviceDTO);
            machineParam.setCreateTime(DateUtils.getNowDate());
            machineParam.setDeviceId(device.getDeviceId());
            machineParamMapper.insertGyMachineParam(machineParam);
            // 如果运行时间超过阈值，则触发预警记录
            Long runTime = Long.parseLong(machineParam.getRunTime());
            String earlyWarnValue = configService.selectConfigByKey("gy.device.earlyWarnValue");
            if (runTime > (Long.parseLong(earlyWarnValue) * 60 * 60)) {

                //触发预警记录
                GyDeviceEarlywarnRecord earlywarnRecord = new GyDeviceEarlywarnRecord();

                earlywarnRecord.setDeviceType(DictUtils.getDictLabel("gy_device_type",
                        gyDeviceDTO.getDeviceType().toString()));
                earlywarnRecord.setDeviceStatus(DeviceStatusEnum.WARNING.getInfo());
                earlywarnRecord.setLocationName(DictUtils.getDictLabel("gy_locations",
                        gyDeviceDTO.getLocationId().toString()));
                earlywarnRecord.setDeviceno(device.getDeviceno());
                earlywarnRecord.setDeviceName(gyDeviceDTO.getDeviceName());
                earlywarnRecord.setMemo("运行时间超过系统设置的阈值");
                earlywarnRecordService.insertGyDeviceEarlywarnRecord(earlywarnRecord);
                //出发工单和站内信
                GyWorkOrder gyWorkOrder = new GyWorkOrder();
                gyWorkOrder.setName(("设备" + device.getDeviceName() + "预警。"));
                gyWorkOrder.setDeviceType(device.getDeviceType());
                gyWorkOrder.setDescription("设备" + device.getDeviceName() + "预警 ,原因：运行时间超过系统设置的阈值。");
                gyWorkOrder.setWorkStatus(Integer.parseInt(WorkOrderStatusEnum.WAIT.getCode()));
                gyWorkOrder.setWorkType(WorkOrderTypeEnum.EARLYWARN.getCode()); //设置工单类型为预警

                AjaxResult result = gyWorkOrderService.insertGyWorkOrder(gyWorkOrder);
                return result;
            }
        } else if (gyDeviceDTO.getDeviceType().equals(DeviceTypeEnum.ARM.getCode())) {
            GyArmParam gyArmParam = new GyArmParam();
            BeanUtils.copyBeanProp(gyArmParam, gyDeviceDTO);

            gyArmParam.setDeviceId(device.getDeviceId());

            gyArmParam.setCreateTime(DateUtils.getNowDate());
            armParamMapper.insertGyArmParam(gyArmParam);
        }

        if (gyDeviceDTO.getDeviceStatus().equals(DeviceStatusEnum.WARNING.getCode())) {
            //触发告警记录
            GyDeviceAlarmRecord alarmRecord = new GyDeviceAlarmRecord();
            alarmRecord.setLocationName(DictUtils.getDictLabel("gy_locations",
                    gyDeviceDTO.getLocationId().toString()));
            alarmRecord.setDeviceType(DictUtils.getDictLabel("gy_device_type",
                    gyDeviceDTO.getDeviceType().toString()));
            alarmRecord.setDeviceStatus(DeviceStatusEnum.WARNING.getInfo());
            alarmRecord.setDeviceName(gyDeviceDTO.getDeviceName());
            alarmRecord.setDeviceno(device.getDeviceno());
            alarmRecord.setCreateBy("admin");
            alarmRecord.setCreateTime(DateUtils.getNowDate());
            deviceAlarmRecordMapper.insertGyDeviceAlarmRecord(alarmRecord);
        }


        return AjaxResult.success();
    }

    /**
     * 修改设备管理
     *
     * @param gyDevice 设备管理
     * @return 结果
     */
    @Override
    public int updateGyDevice(GyDevice gyDevice) {
        gyDevice.setUpdateTime(DateUtils.getNowDate());
        return gyDeviceMapper.updateGyDevice(gyDevice);
    }

    /**
     * 批量删除设备管理
     *
     * @param deviceIds 需要删除的设备管理主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteGyDeviceByDeviceIds(String deviceIds) {
        armParamMapper.deleteGyArmParamByDeviceId(Long.parseLong(deviceIds));
        machineParamMapper.deleteGyMachineParamByDeviceId(Long.parseLong(deviceIds));
        return gyDeviceMapper.deleteGyDeviceByDeviceId(Long.parseLong(deviceIds));
    }

    /**
     * 删除设备管理信息
     *
     * @param deviceId 设备管理主键
     * @return 结果
     */
    public int deleteGyDeviceByDeviceId(Long deviceId) {
        return gyDeviceMapper.deleteGyDeviceByDeviceId(deviceId);
    }


    public Long insertDeviceRecord(GyDevice device) {
        GyDeviceRecord record = new GyDeviceRecord();
        BeanUtils.copyBeanProp(record, device);
        record.setCreateTime(DateUtils.getNowDate());

        record.setLocationName(DictUtils.getDictLabel("gy_locations",
                device.getLocationId().toString()));
        record.setDeviceType(DictUtils.getDictLabel("gy_device_type",
                device.getDeviceType().toString()));
        record.setDeviceStatus(DictUtils.getDictLabel("gy_device_status",
                device.getDeviceStatus().toString()));
        deviceRecordMapper.insertGyDeviceRecord(record); //插入历史记录
        return record.getRecordId();
    }

    /**
     * 设备类型为机床的数据同步
     */
    private void machineSync(GyDeviceDTO deviceDTO, Long deviceHistoryId) {
        GyDevice device  = new GyDevice();
        BeanUtils.copyBeanProp(device, deviceDTO);

        GyMachineParam machineParam = machineParamMapper.selectGyMachineParamByDeviceId(device.getDeviceId());
        GyMachineParamRecord machineParamRecord = new GyMachineParamRecord();
        BeanUtils.copyBeanProp(machineParamRecord, machineParam);
        machineParamRecord.setRecordId(deviceHistoryId);  //记录机床历史记录信息
        machineParamRecordService.insertGyMachineParamRecord(machineParamRecord);
        BeanUtils.copyBeanProp(machineParam, deviceDTO);
        machineParam.setUpdateTime(DateUtils.getNowDate());
        machineParamMapper.updateGyMachineParam(machineParam);
        // 如果开机时间超过阈值，则触发预警记录
        Long runTime = Long.parseLong(machineParam.getRunTime());
        String earlyWarnValue = configService.selectConfigByKey("gy.device.earlyWarnValue");
        if (runTime > (Long.parseLong(earlyWarnValue) * 60 * 60)) {
            //触发预警记录
            GyDeviceEarlywarnRecord earlywarnRecord = new GyDeviceEarlywarnRecord();
            earlywarnRecord.setDeviceType(DictUtils.getDictLabel("gy_device_type",
                    device.getDeviceType().toString()));
            earlywarnRecord.setLocationName(DictUtils.getDictLabel("gy_locations",
                    device.getLocationId().toString()));
            earlywarnRecord.setDeviceName(device.getDeviceName());
            earlywarnRecord.setDeviceStatus(DeviceStatusEnum.ERROR.getInfo());
            earlywarnRecord.setDeviceno(device.getDeviceno());
            earlywarnRecord.setMemo("运行时间超过系统设置的阈值");
            earlywarnRecordService.insertGyDeviceEarlywarnRecord(earlywarnRecord);
            //记录机床的历史信息
            GyMachineParamRecord earlyMachineParamRecord = new GyMachineParamRecord();
            BeanUtils.copyBeanProp(earlyMachineParamRecord, deviceDTO);
            earlyMachineParamRecord.setRecordId(earlywarnRecord.getEarlyWarnId());
            machineParamRecordService.insertGyMachineParamRecord(earlyMachineParamRecord);
            //出发工单和站内信
            sendWorkOrder(device, "预警");
            device.setDeviceStatus(DeviceStatusEnum.ERROR.getCode());
        }
        device.setUpdateTime(DateUtils.getNowDate());
        gyDeviceMapper.updateGyDevice(device);
    }


    /**
     * 修改设备管理
     *
     * @param gyDevice 设备管理
     * @return 结果
     */
    @Transactional
    public AjaxResult update(GyDeviceDTO gyDevice) {
        GyDevice device = gyDeviceMapper.selectGyDeviceByDeviceId(gyDevice.getDeviceId());
        Long deviceHistoryId = insertDeviceRecord(device);
        gyDevice.setDeviceno(device.getDeviceno());


        int deviceType = gyDevice.getDeviceType().intValue();
        if (deviceType == DeviceTypeEnum.MACHINE.getCode()) { //机床
            machineSync(gyDevice, deviceHistoryId);
        } else if (deviceType == DeviceTypeEnum.ARM.getCode()) {
            armSync(gyDevice, deviceHistoryId);
        }

        if (gyDevice.getDeviceStatus()  == DeviceStatusEnum.WARNING.getCode()) {
            //触发告警记录
            deviceWarningHandler(gyDevice);
        }


        return AjaxResult.success();
    }

    private AjaxResult deviceWarningHandler(GyDeviceDTO deviceDTO) {

        GyDevice device  = new GyDevice();
        BeanUtils.copyBeanProp(device, deviceDTO);

        GyDeviceAlarmRecord alarmRecord = new GyDeviceAlarmRecord();

        alarmRecord.setLocationName(DictUtils.getDictLabel("gy_locations",
                device.getLocationId().toString()));
        alarmRecord.setDeviceType(DictUtils.getDictLabel("gy_device_type",
                device.getDeviceType().toString()));
        alarmRecord.setDeviceName(device.getDeviceName());
        alarmRecord.setDeviceStatus(DeviceStatusEnum.WARNING.getInfo());
        alarmRecord.setDeviceno(device.getDeviceno());
        alarmRecord.setCreateBy("admin");
        alarmRecord.setCreateTime(DateUtils.getNowDate());
        deviceAlarmRecordMapper.insertGyDeviceAlarmRecord(alarmRecord);

        //记录设备的参数
        if (device.getDeviceType().equals(DeviceTypeEnum.MACHINE.getCode())) {//机床
            GyMachineParamRecord machineParamRecord = new GyMachineParamRecord();
            BeanUtils.copyBeanProp(machineParamRecord, deviceDTO);
            machineParamRecord.setRecordId(alarmRecord.getAlarmId());
            machineParamRecordService.insertGyMachineParamRecord(machineParamRecord);

        } else if (device.getDeviceType().equals(DeviceTypeEnum.ARM.getCode())) {
            GyArmParamRecord gyArmParamRecord = new GyArmParamRecord();
            BeanUtils.copyBeanProp(gyArmParamRecord, deviceDTO);
            gyArmParamRecord.setRecordId(alarmRecord.getAlarmId());
            armParamRecordService.insertGyArmParamRecord(gyArmParamRecord);
        }
        AjaxResult ajaxResult = sendWorkOrder(device, "告警");
        return ajaxResult;
    }

    private AjaxResult sendWorkOrder(GyDevice device, String status) {
        //出发工单和站内信
        GyWorkOrder gyWorkOrder = new GyWorkOrder();
        gyWorkOrder.setName(("设备" + device.getDeviceName() + status));
        gyWorkOrder.setDeviceType(device.getDeviceType());
        gyWorkOrder.setDescription("设备" + device.getDeviceName() + status);
        gyWorkOrder.setWorkStatus(Integer.parseInt(WorkOrderStatusEnum.WAIT.getCode()));
        if (status.equals("告警")) {
            gyWorkOrder.setWorkType(WorkOrderTypeEnum.ALARM.getCode());
        } else {
            gyWorkOrder.setWorkType(WorkOrderTypeEnum.EARLYWARN.getCode());
        }
        AjaxResult result = gyWorkOrderService.insertGyWorkOrder(gyWorkOrder);
        return result;
    }

    private void armSync(GyDeviceDTO deviceDTO, Long deviceHistoryId) {
        GyDevice device  = new GyDevice();
        BeanUtils.copyBeanProp(device, deviceDTO);


        GyArmParam gyArmParam = armParamMapper.selectGyArmParamByDeviceId(device.getDeviceId());
        GyArmParamRecord gyArmParamRecord = new GyArmParamRecord();
        BeanUtils.copyBeanProp(gyArmParamRecord, gyArmParam);
        gyArmParamRecord.setRecordId(deviceHistoryId);
        gyArmParamRecord.setCreateTime(DateUtils.getNowDate());
        armParamRecordService.insertGyArmParamRecord(gyArmParamRecord);

        BeanUtils.copyBeanProp(gyArmParam, deviceDTO);

        gyArmParam.setUpdateTime(DateUtils.getNowDate());
        armParamMapper.updateGyArmParam(gyArmParam);
        device.setUpdateTime(DateUtils.getNowDate());
        gyDeviceMapper.updateGyDevice(device);
    }

    /**
     * 根据设备类型统计数量
     *
     * @param gyDevice 设备管理
     * @return 总数
     */
    public Integer selectGyDeviceByDeviceTypeAndStatus(GyDevice gyDevice) {
        return gyDeviceMapper.selectGyDeviceByDeviceTypeAndStatus(gyDevice);
    }

    /**
     * 根据设备类型统计
     *
     * @param gyDevice 设备管理
     * @return 设备管理集合
     */
    public List<GyDevice> selectGyDeviceByDeviceType(GyDevice gyDevice) {
        return gyDeviceMapper.selectGyDeviceByDeviceType(gyDevice);
    }


    /**
     * 查询所有学院状态统计总数
     *
     * @param gyDevice 设备管理
     * @return 设备管理集合
     */
    public Integer selectDeviceStatusCountByLocations(GyDevice gyDevice) {
        return gyDeviceMapper.selectDeviceStatusCountByLocations(gyDevice);
    }

    /**
     * 查询所有学院设备类型分类总数
     *
     * @param gyDevice 设备管理
     * @return 设备管理集合
     */
    public Integer selectDeviceStatusDistributeByLocations(GyDevice gyDevice) {
        return gyDeviceMapper.selectDeviceStatusDistributeByLocations(gyDevice);
    }

    /**
     * 查询所有实时报警数据
     *
     * @param gyDevice 设备管理
     * @return 设备管理集合
     */
    public List<DeviceAlarmRecordDTO> selectDeviceStatusRecord(GyDevice gyDevice) {
        return gyDeviceMapper.selectDeviceStatusRecord(gyDevice);
    }

    /**
     * 设备种类数据为列表数据
     *
     * @param gyDevice 设备管理
     * @return 设备管理集合
     */
    public List<NameValueDataDTO> selectDeviceTypeCountRecord(GyDevice gyDevice) {
        return gyDeviceMapper.selectDeviceTypeCountRecord(gyDevice);
    }

    /**
     * 查询所有实时报警数据
     *
     * @param gyDevice 设备管理
     * @return 所有实时报警数据集合
     */
    public List<NameValueDataDTO> selectDeviceAlarmRecord(GyDevice gyDevice) {
        return gyDeviceMapper.selectDeviceAlarmRecord(gyDevice);
    }

    /**
     * 查询所有实时报警数据
     *
     * @param gyDevice 设备管理
     * @return 所有实时报警数据集合
     */
    public List<Map> selectDeviceStatusTotalByLocationId(GyDevice gyDevice) {
        return gyDeviceMapper.selectDeviceStatusTotalByLocationId(gyDevice);
    }

    /**
     * 根据学院编号查询学院下面的设备报警实时数据
     *
     * @param gyDevice 设备管理
     * @return 返回学院编号查询学院下面的设备报警实时数据
     */
    public List<DeviceAlarmRecordDTO> selectAlarmRecordByLocationId(GyDevice gyDevice) {
        return gyDeviceMapper.selectAlarmRecordByLocationId(gyDevice);
    }


    /**
     * 根据学院编号查询学院下面的所有设备
     *
     * @param gyDevice 设备管理
     * @return 返回学院编号查询学院下面的所有设备
     */
    public List<LocationDeviceDTO> selectDevicesByLocationId(GyDevice gyDevice) {
        return gyDeviceMapper.selectDevicesByLocationId(gyDevice);
    }


    /**
     * 查询最大的id
     *
     * @return
     */
    public Integer selectMaxId() {
        return gyDeviceMapper.selectMaxId();
    }


    /**
     * 设备分析，机床运行时间、产量统计
     * @return
     */
    public List<MachineInfoDTO>  selectDeviceMachineAnalyInfo(GyDevice gyDevice){
        return gyDeviceMapper.selectDeviceMachineAnalyInfo(gyDevice);
    }


    /**
     * 返回设备总数
     *
     * @return 设备告警记录集合
     */
    public int selectTotal(){
        return gyDeviceMapper.selectTotal();
    }
}
